import asyncio
import datetime
import sqlite3

from aiogram import Router, types, F
from aiogram.fsm.context import FSMContext
from aiogram.utils.markdown import hpre, hbold

import async_db
import config
from loader import db, bot, scheduler, logger
from keyboards import menu_keys
from keyboards.callbacks_data import MenuCategory
from utils import User, StopWordsStates

router = Router()
router.message.filter(F.chat.type == "private")
router.callback_query.filter(
    # MenuCategory.filter(F.category == "stop_Words")
)


async def parse_words_from_message(m: types.Message):
    lines = m.text.split('\n')
    return lines


async def collect_words(m: types.Message):
    lines = m.text.split('\n')
    words = []

    # если одна строка и после команды что-то написанно
    if len(lines) == 1 and len(lines[0].split()) > 1:
        # склеиваем слова после команды и добавляем в общий список
        word = ' '.join([i.strip() for i in lines[0].split()[1::]])
        words.append(word)

    # Если строк больше
    elif len(lines) > 1:
        # В первой строчке не только команда
        if len(lines[0].split()) > 1:
            word = ' '.join([i.strip() for i in lines[0].split()[1::]])
            words.append(word)
        for line in lines[1::]:
            words.append(line.strip())
    return words


@router.message(commands='stop_add')
async def add_world(m: types.Message, context: dict):
    words = await collect_words(m)
    processed_words = []

    for w in words:
        try:
            db.add_word(m.from_user.id, w)
            processed_words.append(f"✅ {w} - добавленно в список стоп слов")
            await asyncio.sleep(1)
        except sqlite3.IntegrityError as e:
            if 'UNIQUE constraint failed' in str(e):
                processed_words.append(f'❌ {w} - Уже есть в списке')
                continue

    words_success = "\n".join(processed_words)
    text = f'{hpre(words_success)}'
    await m.reply(text)
    context['users'] = db.get_all_clients()


@router.message(commands='stop_del')
async def stop_delete(m: types.Message, context: dict):
    words = await collect_words(m)
    processed_words = []

    for w in words:
        try:
            db.delete_word(m.from_user.id, w)
            processed_words.append(f"✅ {w} - удалено из списка стоп слов")
            await asyncio.sleep(1)
        except Exception as e:
            logger.error(e)
            processed_words.append(f'❌ {w} - Ошибка')
            continue

    words_success = "\n".join(processed_words)
    text = f'{hpre(words_success)}'
    to_delete = await m.reply(text)
    context['users'] = db.get_all_clients()
    # context['stop_words'] = [word[1] for word in db.select_default_word()]


@router.message(commands='default_list')
async def list_default(m: types.Message, context: dict, user_id=None):
    words = db.select_default_word()
    messages = []
    temp_text = ''
    for i in words:
        temp_text += f"{i}\n"
        if len(temp_text) > 4000:
            messages.append(temp_text)
            temp_text = ''
        if i is words[-1]:
            messages.append(temp_text)

    for list_words in messages:
        text = f'Список слов, удаляющихся по умолчанию: \n{hpre(list_words)}'
        if len(messages) > 1 and list_words not in messages[0]:
            text = hpre(list_words)
        await m.answer(text)


@router.message(commands='stop_list')
async def list_stop_worlds(m: types.Message, context: dict, user_id=None):
    if not user_id:
        user_id = m.from_user.id
        # await m.delete()
    stop_words = []
    users = context["users"]
    for c in users:
        if c.client_id == user_id:
            stop_words = c.stop_words
            break

    # drop to messages
    messages = []
    temp_text = ''
    for i in stop_words:
        temp_text += f"{i}\n"
        if len(temp_text) > 4000:
            messages.append(temp_text)
            temp_text = ''
        if i is stop_words[-1]:
            messages.append(temp_text)

    for list_words in messages:
        no_words = 'Сюда пока что ничего не добавили((\nНажми на кнопку ниже чтобы добавить нужные тебе слова ' \
                   'или напиши <code>/stop_add </code>[слово] - чтобы добавить слово в фильтр\n' \
                   'Также есть список слов сообщения с которыми удаляются по умолчанию. посмотреть их можно по команде ' \
                   '/default_list'
        text = f'Список всех стоп слов: \n{hpre(list_words)}' if len(stop_words) > 0 else no_words
        if len(messages) > 1 and list_words not in messages[0]:
            text = hpre(list_words)
        await m.answer(text)


@router.callback_query(
    MenuCategory.filter(F.category == 'stop_words'),
    MenuCategory.filter(F.action == 'list'),
)
async def list_worlds(call: types.CallbackQuery, callback_data: MenuCategory, context: dict):
    await list_stop_worlds(call.message, context, call.from_user.id)


@router.callback_query(
    MenuCategory.filter(F.category == 'stop_words'),
    MenuCategory.filter(F.action.in_({'add', 'delete'})),
)
async def add_del_words(call: types.CallbackQuery, callback_data: MenuCategory, context: dict, state: FSMContext):
    users = context["users"]
    words = []
    for user in users:
        if call.from_user.id == user.client_id:
            words = user.stop_words
    words_list = '\n'.join(words)

    if callback_data.action == 'add':
        await state.set_state(StopWordsStates.add)
        await call.message.edit_text(
            f"Твой список:\n{hpre(words_list[:3900])}\n\nЕсли список не полный нажми /stop_list\n\n"
            f"Напиши мне что хочешь добавить. Можно добавить или удалить сразу нескольслко стоп слов."
            "Для этого разделяй их по строкам")
        await call.message.edit_reply_markup(menu_keys.back(2, 'stop_words'))
    elif callback_data.action == 'delete':
        await state.set_state(StopWordsStates.delete)
        await call.message.edit_text(
            f"Твой список:\n{hpre(words_list[:3900])}\n\nЕсли список не полный нажми /stop_list\n\n"
            f"Напиши мне что хочешь удалить. Можно добавить или удалить сразу нескольслко стоп слов."
            "Для этого разделяй их по строкам")
        await call.message.edit_reply_markup(menu_keys.back(2, 'stop_words'))
    await state.update_data(call=call)
    scheduler.add_job(state.clear, trigger='date',
                      run_date=datetime.datetime.now() + datetime.timedelta(minutes=1))


async def delete_mess(m: types.Message):
    await m.delete()


@router.message(StopWordsStates.add)
async def stop_words_add(m: types.Message, context: FSMContext, state: FSMContext):
    data = await state.get_data()
    call = data['call']
    words = m.text.split('\n')
    for word in words:
        db.add_word(m.from_user.id, word)
    context['users'] = db.get_all_clients()
    mess = await m.answer(f"Добавил: {hbold(m.text)}")
    await m.delete()
    await add_del_words(call, MenuCategory(level=2, category='stop_words', action='add'), context, state)
    scheduler.add_job(delete_mess, args=(mess,), trigger='date',
                      run_date=datetime.datetime.now() + datetime.timedelta(seconds=10))


@router.message(StopWordsStates.delete)
async def stop_words_dell(m: types.Message, context: FSMContext, state: FSMContext):
    data = await state.get_data()
    call = data['call']
    words = m.text.split('\n')
    for word in words:
        db.delete_word(m.from_user.id, word)
    context['users'] = db.get_all_clients()
    mess = await m.answer(f"Удалил: {hbold(m.text)}")
    await m.delete()
    await add_del_words(call, MenuCategory(level=2, category='stop_words', action='add'), context, state)
    scheduler.add_job(delete_mess, args=(mess,), trigger='date',
                      run_date=datetime.datetime.now() + datetime.timedelta(seconds=10))


@router.callback_query(
    MenuCategory.filter(F.category == 'stop_words'),
)
async def show_menu(call: types.CallbackQuery, callback_data: MenuCategory, context: dict, state: FSMContext):
    # TODO: drop stop words in parts of 4000 letters
    current_level = callback_data.level
    if callback_data.action == 'back':
        if current_level == 2:
            await state.clear()
        current_level -= 1
    user_id = call.from_user.id
    users = context["users"]
    stop_words = []
    for c in users:
        if c.client_id == user_id:
            stop_words = c.stop_words
            break
    stop_words = '\n'.join(stop_words)
    # print(len(stop_words))
    if len(stop_words) > 4000:
        stop_words = f'{stop_words[:4000]}\n' \
                     f'Ой! у вас очень много слов и они не помещаются в одно сообщение. ' \
                     f'Нажми /stop_list чтобы увидеть весь список'

    levels = {
        0: menu_keys.admin_menu() if call.from_user.id in config.ADMIN_ID else menu_keys.client_menu(),
        1: menu_keys.action(2, 'stop_words'),
        2: menu_keys.back(3, 'stop_words')
    }
    texts = {
        0: "Вот чем вы можете управлять:",
        1: f"Вот ваши слова:\n<code>{stop_words}</code>\n\nДоступны такие действия: \n",
        2: "Напиши слова/фразы, которые хочешь добавить. Можно добавить или удалить сразу нескольслко стоп слов."
           "Для этого разделяй их по строкам"
    }
    await call.message.edit_text(texts[current_level])
    await call.message.edit_reply_markup(levels[current_level])
